#include <iostream>
#include <memory>
#include <string>
using namespace std;

// 抽象组件类：饮品
class Beverage
{
public:
    virtual string getDescription() const = 0;
    virtual double cost() const = 0;
    virtual ~Beverage() = default;
};

// 具体组件类：基础咖啡
class Coffee : public Beverage
{
public:
    string getDescription() const override
    {
        return "Coffee";
    }
    double cost() const override
    {
        return 5.0; // 基础价格
    }
};

// 抽象装饰器类：继承自 Beverage
class CondimentDecorator : public Beverage
{
protected:
    shared_ptr<Beverage> beverage; // 被装饰的饮品
public:
    CondimentDecorator(shared_ptr<Beverage> b) : beverage(b) {}
};

// 具体装饰器：加牛奶
class Milk : public CondimentDecorator
{
public:
    Milk(shared_ptr<Beverage> b) : CondimentDecorator(b) {}
    string getDescription() const override
    {
        return beverage->getDescription() + ", Milk";
    }
    double cost() const override
    {
        return beverage->cost() + 1.5; // 牛奶加价
    }
};

// 具体装饰器：加糖
class Sugar : public CondimentDecorator
{
public:
    Sugar(shared_ptr<Beverage> b) : CondimentDecorator(b) {}
    string getDescription() const override
    {
        return beverage->getDescription() + ", Sugar";
    }
    double cost() const override
    {
        return beverage->cost() + 0.8; // 糖加价
    }
};

// 具体装饰器：加奶泡
class Foam : public CondimentDecorator
{
public:
    Foam(shared_ptr<Beverage> b) : CondimentDecorator(b) {}
    string getDescription() const override
    {
        return beverage->getDescription() + ", Foam";
    }
    double cost() const override
    {
        return beverage->cost() + 2.0;
    }
};

int main()
{
    // 基础咖啡
    shared_ptr<Beverage> coffee = make_shared<Coffee>();
    cout << coffee->getDescription() << " $" << coffee->cost() << endl;

    // 加牛奶的咖啡
    shared_ptr<Beverage> milkCoffee = make_shared<Milk>(coffee);
    cout << milkCoffee->getDescription() << " $" << milkCoffee->cost() << endl;

    // 加牛奶 + 糖的咖啡
    shared_ptr<Beverage> sweetMilkCoffee = make_shared<Sugar>(milkCoffee);
    cout << sweetMilkCoffee->getDescription() << " $" << sweetMilkCoffee->cost() << endl;

    // 加牛奶 + 糖 + 奶泡的咖啡
    shared_ptr<Beverage> fullCoffee = make_shared<Foam>(sweetMilkCoffee);
    cout << fullCoffee->getDescription() << " $" << fullCoffee->cost() << endl;
    return 0;
}
